#include "game_log.h"
#include "game_macros.h"
#include <chrono>
extern "C" {
#include <log4c/appender_type_stream.h>
#include <log4c/appender_type_rollingfile.h>
#include <log4c/layout_type_dated.h>
}

CGameLoggerFactory *CGameLoggerFactory::_ins = NULL;


const char *__log4c_foramt(const log4c_layout_t *a_layout, const log4c_logging_event_t *a_event)
{
  static char buffer[1024];

  // Linux, Mac, iOS, etc
  time_t tt = time(NULL);
  tm *t = localtime(&tt);

  std::chrono::system_clock::time_point tp = std::chrono::system_clock::now();
  time_t raw_time = std::chrono::system_clock::to_time_t(tp);
  // tm只能到秒，毫秒需要另外获取
  std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());

  std::string milliseconds_str = std::to_string(ms.count() % 1000);

  if (milliseconds_str.length() < 3)
  {
    milliseconds_str = std::string(3 - milliseconds_str.length(), '0') + milliseconds_str;
  }

  snprintf(buffer, sizeof(buffer), "%d-%02d-%02d %02d:%02d:%02d.%s %5s --- [%16s] : %s\n",
    t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
    t->tm_hour, t->tm_min, t->tm_sec,
    milliseconds_str.c_str(),
    log4c_priority_to_string(a_event->evt_priority),
    a_event->evt_category, a_event->evt_msg);

  return buffer;
}





const log4c_layout_type_t log4c_layout_type_date = {
    "date",
    __log4c_foramt,
};

log4c_appender_t *__log4c_appender_get(log4c_layout_t *layout)
{
  log4c_appender_t *ret = log4c_appender_get("stdout");
  log4c_appender_set_type(ret, &log4c_appender_type_stream);
  log4c_appender_set_layout(ret, layout);
  return ret;
}

log4c_layout_t *__log4c_layout_get()
{
  log4c_layout_t *ret = log4c_layout_get("date");
  log4c_layout_set_type(ret, &log4c_layout_type_date);
  return ret;
}



int CGame::Logger::__log4c_appender_type_file_open(log4c_appender_t *a_appender)
{
  CGame::Logger::FileLoggerFactory *factory = (CGame::Logger::FileLoggerFactory*)log4c_appender_get_udata(a_appender);
  return factory->open();
}

int CGame::Logger::__log4c_appender_type_file_close(log4c_appender_t *a_appender)
{
  CGame::Logger::FileLoggerFactory *factory = (CGame::Logger::FileLoggerFactory*)log4c_appender_get_udata(a_appender);
  return factory->close();
}

int CGame::Logger::__log4c_appender_type_file_append(log4c_appender_t *a_appender, const log4c_logging_event_t *a_event)
{
  CGame::Logger::FileLoggerFactory *factory = (CGame::Logger::FileLoggerFactory*)log4c_appender_get_udata(a_appender);
  return factory->append(a_event);
}


const log4c_appender_type_t log4c_appender_type_file = {
  "file",
  CGame::Logger::__log4c_appender_type_file_open,
  CGame::Logger::__log4c_appender_type_file_append,
  CGame::Logger::__log4c_appender_type_file_close,
};


BOOL CGameLoggerFactory::init(CGame::Logger::PriorityLevel_t priority){
  do
  {
    int ret;
    _priority = priority;
    CC_BREAK_IF(0 != (ret = log4c_init()));

    CGameLogger *logger = getLogger("root");
    return TRUE;
  } while (true);

  return FALSE;
}


BOOL CGameLoggerFactory::init()
{
  return init(CGame::Logger::PriorityLevel_t::LOG4C_PRIORITY_INFO);
}

BOOL CGame::Logger::StdoutLoggerFactory::init()
{
  do
  {
    // int ret;

    _log4c_layout = __log4c_layout_get();

    _log4c_appender = log4c_appender_get("stdout");
    log4c_appender_set_type(_log4c_appender, &log4c_appender_type_stream);
    log4c_appender_set_layout(_log4c_appender, _log4c_layout);

    // //初始化
    CC_BREAK_IF(!CGameLoggerFactory::init());

    return TRUE;
  } while (true);

  return FALSE;
}



BOOL CGame::Logger::FileLoggerFactory::init(){
  do
  {

    _log4c_layout = __log4c_layout_get();

    // _log4c_appender = __log4c_appender_get(_log4c_layout);
    // log4c_appender_set_type(_log4c_appender, &log4c_appender_type_stream);
    // log4c_appender_set_layout(_log4c_appender, _log4c_layout);

    // log4c_appender_print(&log4c_appender_type_rollingfile,stdout);

    _log4c_appender = log4c_appender_get("file");
    log4c_appender_set_udata(_log4c_appender,this);
    log4c_appender_set_type(_log4c_appender, &log4c_appender_type_file);
    log4c_appender_set_layout(_log4c_appender, _log4c_layout);

    // log4c_appender_print(_log4c_appender,stdout);

    // //初始化
    CC_BREAK_IF(!CGameLoggerFactory::init());

    return TRUE;
  } while (true);

  return FALSE;
}
